﻿namespace Pub.Class
{
    using Microsoft.VisualBasic;
    using System;
    using System.Data.SqlTypes;
    using System.Globalization;
    using System.Runtime.CompilerServices;
    using System.Text;

    public static class DateExtensions
    {
        private static readonly TimeSpan _OneDay = new TimeSpan(1, 0, 0, 0);
        private static readonly TimeSpan _OneHour = new TimeSpan(1, 0, 0);
        private static readonly TimeSpan _OneMinute = new TimeSpan(0, 1, 0);
        private static readonly TimeSpan _OneMonth = new TimeSpan(0x1f, 0, 0, 0);
        private static readonly TimeSpan _OneWeek = new TimeSpan(7, 0, 0, 0);
        private static readonly TimeSpan _OneYear = new TimeSpan(0x16d, 0, 0, 0);
        private static readonly TimeSpan _TwoDays = new TimeSpan(2, 0, 0, 0);
        private static readonly TimeSpan _TwoHours = new TimeSpan(2, 0, 0);
        private static readonly TimeSpan _TwoMinutes = new TimeSpan(0, 2, 0);
        private static readonly TimeSpan _TwoMonths = new TimeSpan(0x3e, 0, 0, 0);
        private static readonly TimeSpan _TwoWeeks = new TimeSpan(14, 0, 0, 0);
        private static readonly TimeSpan _TwoYears = new TimeSpan(730, 0, 0, 0);

        private static long DateDiff(this DateInterval interval, DateTime date1, DateTime date2)
        {
            if (interval == DateInterval.Year)
            {
                return (long) (date2.Year - date1.Year);
            }
            if (interval == DateInterval.Month)
            {
                return (long) ((date2.Month - date1.Month) + (12 * (date2.Year - date1.Year)));
            }
            TimeSpan span = (TimeSpan) (date2 - date1);
            if ((interval == DateInterval.Day) || (interval == DateInterval.DayOfYear))
            {
                return span.TotalDays.Round();
            }
            if (interval == DateInterval.Hour)
            {
                return span.TotalHours.Round();
            }
            if (interval == DateInterval.Minute)
            {
                return span.TotalMinutes.Round();
            }
            if (interval == DateInterval.Second)
            {
                return span.TotalSeconds.Round();
            }
            if (interval == DateInterval.Weekday)
            {
                return (span.TotalDays / 7.0).Round();
            }
            if (interval == DateInterval.WeekOfYear)
            {
                while (date2.DayOfWeek != DateTimeFormatInfo.CurrentInfo.FirstDayOfWeek)
                {
                    date2 = date2.AddDays(-1.0);
                }
                while (date1.DayOfWeek != DateTimeFormatInfo.CurrentInfo.FirstDayOfWeek)
                {
                    date1 = date1.AddDays(-1.0);
                }
                span = (TimeSpan) (date2 - date1);
                return (span.TotalDays / 7.0).Round();
            }
            if (interval == DateInterval.Quarter)
            {
                double quarter = date1.Month.GetQuarter();
                double num2 = date2.Month.GetQuarter();
                double num3 = num2 - quarter;
                double num4 = 4 * (date2.Year - date1.Year);
                return (num3 + num4).Round();
            }
            return 0L;
        }

        public static long DateDiff(this DateTime value, DateTime date, DateInterval interval)
        {
            if (interval == DateInterval.Year)
            {
                return (long) (date.Year - value.Year);
            }
            if (interval == DateInterval.Month)
            {
                return (long) ((date.Month - value.Month) + (12 * (date.Year - value.Year)));
            }
            TimeSpan span = (TimeSpan) (date - value);
            if ((interval == DateInterval.Day) || (interval == DateInterval.DayOfYear))
            {
                return span.TotalDays.Round();
            }
            if (interval == DateInterval.Hour)
            {
                return span.TotalHours.Round();
            }
            if (interval == DateInterval.Minute)
            {
                return span.TotalMinutes.Round();
            }
            if (interval == DateInterval.Second)
            {
                return span.TotalSeconds.Round();
            }
            if (interval == DateInterval.Weekday)
            {
                return (span.TotalDays / 7.0).Round();
            }
            if (interval == DateInterval.WeekOfYear)
            {
                while (date.DayOfWeek != DateTimeFormatInfo.CurrentInfo.FirstDayOfWeek)
                {
                    date = date.AddDays(-1.0);
                }
                while (value.DayOfWeek != DateTimeFormatInfo.CurrentInfo.FirstDayOfWeek)
                {
                    value = value.AddDays(-1.0);
                }
                span = (TimeSpan) (date - value);
                return (span.TotalDays / 7.0).Round();
            }
            if (interval == DateInterval.Quarter)
            {
                double quarter = value.Month.GetQuarter();
                double num2 = date.Month.GetQuarter();
                double num3 = num2 - quarter;
                double num4 = 4 * (date.Year - value.Year);
                return (num3 + num4).Round();
            }
            return 0L;
        }

        public static DateTime DayBegin(this DateTime date)
        {
            return new DateTime(date.Year, date.Month, date.Day, 0, 0, 0, 0);
        }

        public static DateTime DayEnd(this DateTime date)
        {
            return new DateTime(date.Year, date.Month, date.Day, 0x17, 0x3b, 0x3b, 990);
        }

        public static int GetCountDaysOfMonth(this DateTime date)
        {
            DateTime time = date.AddMonths(1);
            DateTime time2 = new DateTime(time.Year, time.Month, 1);
            return time2.AddDays(-1.0).Day;
        }

        public static DateTime GetFirstDayOfMonth(this DateTime date)
        {
            return new DateTime(date.Year, date.Month, 1);
        }

        public static DateTime GetFirstDayOfMonth(this DateTime date, DayOfWeek dayOfWeek)
        {
            DateTime firstDayOfMonth = date.GetFirstDayOfMonth();
            while (firstDayOfMonth.DayOfWeek != dayOfWeek)
            {
                firstDayOfMonth = firstDayOfMonth.AddDays(1.0);
            }
            return firstDayOfMonth;
        }

        public static DateTime GetFirstDayOfWeek(this DateTime date)
        {
            return date.GetFirstDayOfWeek(null);
        }

        public static DateTime GetFirstDayOfWeek(this DateTime date, CultureInfo cultureInfo)
        {
            cultureInfo = cultureInfo ?? CultureInfo.CurrentCulture;
            DayOfWeek firstDayOfWeek = cultureInfo.DateTimeFormat.FirstDayOfWeek;
            while (date.DayOfWeek != firstDayOfWeek)
            {
                date = date.AddDays(-1.0);
            }
            return date;
        }

        public static DateTime GetLastDayOfMonth(this DateTime date)
        {
            return new DateTime(date.Year, date.Month, date.GetCountDaysOfMonth());
        }

        public static DateTime GetLastDayOfMonth(this DateTime date, DayOfWeek dayOfWeek)
        {
            DateTime lastDayOfMonth = date.GetLastDayOfMonth();
            while (lastDayOfMonth.DayOfWeek != dayOfWeek)
            {
                lastDayOfMonth = lastDayOfMonth.AddDays(-1.0);
            }
            return lastDayOfMonth;
        }

        public static DateTime GetLastDayOfWeek(this DateTime date)
        {
            return date.GetLastDayOfWeek(null);
        }

        public static DateTime GetLastDayOfWeek(this DateTime date, CultureInfo cultureInfo)
        {
            return date.GetFirstDayOfWeek(cultureInfo).AddDays(6.0);
        }

        public static DateTime GetNextWeekday(this DateTime date, DayOfWeek weekday)
        {
            while (date.DayOfWeek != weekday)
            {
                date = date.AddDays(1.0);
            }
            return date;
        }

        public static DateTime GetPreviousWeekday(this DateTime date, DayOfWeek weekday)
        {
            while (date.DayOfWeek != weekday)
            {
                date = date.AddDays(-1.0);
            }
            return date;
        }

        public static int GetQuarter(this int month)
        {
            if (month <= 3)
            {
                return 1;
            }
            if (month <= 6)
            {
                return 2;
            }
            if (month <= 9)
            {
                return 3;
            }
            return 4;
        }

        public static TimeSpan GetTimeSpan(this DateTime startTime, DateTime endTime)
        {
            return (TimeSpan) (endTime - startTime);
        }

        public static DateTime GetWeekday(this DateTime date, DayOfWeek weekday)
        {
            return date.GetWeekday(weekday, null);
        }

        public static DateTime GetWeekday(this DateTime date, DayOfWeek weekday, CultureInfo cultureInfo)
        {
            return date.GetFirstDayOfWeek(cultureInfo).GetNextWeekday(weekday);
        }

        public static bool IsLeapYear(this DateTime value)
        {
            return DateTime.IsLeapYear(value.Year);
        }

        public static bool IsOnTime(this DateTime requiredTime, DateTime val, int maxToleranceInSecs)
        {
            TimeSpan span = (TimeSpan) (val - requiredTime);
            double num = (span.TotalMilliseconds < 0.0) ? -span.TotalMilliseconds : span.TotalMilliseconds;
            return (num <= (maxToleranceInSecs * 0x3e8));
        }

        public static bool IsOnTime(this DateTime startTime, DateTime val, int cycleSpanInSecs, int maxToleranceInSecs)
        {
            TimeSpan span = (TimeSpan) (val - startTime);
            double num2 = span.TotalMilliseconds % ((double) (cycleSpanInSecs * 0x3e8));
            return (num2 <= (maxToleranceInSecs * 0x3e8));
        }

        public static bool IsToday(this DateTime dt)
        {
            return (dt.Date == DateTime.Today);
        }

        public static bool IsToday(this DateTimeOffset dto)
        {
            return dto.Date.IsToday();
        }

        public static bool IsWeekday(this DateTime date)
        {
            return !date.IsWeekend();
        }

        public static bool IsWeekend(this DateTime value)
        {
            if (value.DayOfWeek != DayOfWeek.Sunday)
            {
                return (value.DayOfWeek == DayOfWeek.Saturday);
            }
            return true;
        }

        public static DateTime SetTime(this DateTime date, TimeSpan time)
        {
            return date.Date.Add(time);
        }

        public static DateTimeOffset SetTime(this DateTimeOffset date, TimeSpan time)
        {
            return date.SetTime(time, null);
        }

        public static DateTimeOffset SetTime(this DateTimeOffset date, TimeSpan time, TimeZoneInfo localTimeZone)
        {
            DateTime time2 = date.ToLocalDateTime(localTimeZone);
            time2.SetTime(time);
            return time2.ToDateTimeOffset(localTimeZone);
        }

        public static DateTime SetTime(this DateTime date, int hours, int minutes, int seconds)
        {
            return date.SetTime(new TimeSpan(hours, minutes, seconds));
        }

        public static DateTimeOffset SetTime(this DateTimeOffset date, int hours, int minutes, int seconds)
        {
            return date.SetTime(new TimeSpan(hours, minutes, seconds));
        }

        public static int ToAge(this DateTime dateOfBirth)
        {
            return dateOfBirth.ToAge(DateTime.Today);
        }

        public static int ToAge(this DateTime dateOfBirth, DateTime referenceDate)
        {
            int num = referenceDate.Year - dateOfBirth.Year;
            if ((referenceDate.Month < dateOfBirth.Month) || ((referenceDate.Month == dateOfBirth.Month) && (referenceDate.Day < dateOfBirth.Day)))
            {
                num--;
            }
            return num;
        }

        public static string ToAgo(this DateTime date)
        {
            TimeSpan timeSpan = date.GetTimeSpan(DateTime.Now);
            if (timeSpan < TimeSpan.Zero)
            {
                return "未来";
            }
            if (timeSpan < _OneMinute)
            {
                return "现在";
            }
            if (timeSpan < _TwoMinutes)
            {
                return "1 分钟前";
            }
            if (timeSpan < _OneHour)
            {
                return string.Format("{0} 分钟前", timeSpan.Minutes);
            }
            if (timeSpan < _TwoHours)
            {
                return "1 小时前";
            }
            if (timeSpan < _OneDay)
            {
                return string.Format("{0} 小时前", timeSpan.Hours);
            }
            if (timeSpan < _TwoDays)
            {
                return "昨天";
            }
            if (timeSpan < _OneWeek)
            {
                return string.Format("{0} 天前", timeSpan.Days);
            }
            if (timeSpan < _TwoWeeks)
            {
                return "1 周前";
            }
            if (timeSpan < _OneMonth)
            {
                return string.Format("{0} 周前", timeSpan.Days / 7);
            }
            if (timeSpan < _TwoMonths)
            {
                return "1 月前";
            }
            if (timeSpan < _OneYear)
            {
                return string.Format("{0} 月前", timeSpan.Days / 0x1f);
            }
            if (timeSpan < _TwoYears)
            {
                return "1 年前";
            }
            return string.Format("{0} 年前", timeSpan.Days / 0x16d);
        }

        public static string ToAgo(this DateTime time, DateTime currentDateTime)
        {
            if ((currentDateTime.Year == time.Year) && (currentDateTime.Month == time.Month))
            {
                if (DateInterval.Hour.DateDiff(time, currentDateTime) <= 10L)
                {
                    if (DateInterval.Hour.DateDiff(time, currentDateTime) > 0L)
                    {
                        return (DateInterval.Hour.DateDiff(time, currentDateTime) + "小时前");
                    }
                    if (DateInterval.Minute.DateDiff(time, currentDateTime) > 0L)
                    {
                        return (DateInterval.Minute.DateDiff(time, currentDateTime) + "分钟前");
                    }
                    if (DateInterval.Second.DateDiff(time, currentDateTime) >= 0L)
                    {
                        return (DateInterval.Second.DateDiff(time, currentDateTime) + "秒前");
                    }
                    return "刚才";
                }
                switch ((currentDateTime.Day - time.Day))
                {
                    case 0:
                        return ("今天 " + time.ToString("HH") + ":" + time.ToString("mm"));

                    case 1:
                        return ("昨天 " + time.ToString("HH") + ":" + time.ToString("mm"));

                    case 2:
                        return ("前天 " + time.ToString("HH") + ":" + time.ToString("mm"));
                }
                return time.ToString("yyyy-MM-dd HH:mm");
            }
            return time.ToString("yyyy-MM-dd HH:mm");
        }

        public static string ToDate(this DateTime time)
        {
            return time.ToString("yyyy-MM-dd");
        }

        public static string ToDateTime(this DateTime time)
        {
            return time.ToString("yyyy-MM-dd HH:mm:ss");
        }

        public static string ToDateTimeF(this DateTime time)
        {
            return time.ToString("yyyy-MM-dd HH:mm:ss:fffffff");
        }

        public static DateTimeOffset ToDateTimeOffset(this DateTime localDateTime)
        {
            return localDateTime.ToDateTimeOffset(null);
        }

        public static DateTimeOffset ToDateTimeOffset(this DateTime localDateTime, TimeZoneInfo localTimeZone)
        {
            localTimeZone = localTimeZone ?? TimeZoneInfo.Local;
            if (localDateTime.Kind != DateTimeKind.Unspecified)
            {
                localDateTime = new DateTime(localDateTime.Ticks, DateTimeKind.Unspecified);
            }
            return TimeZoneInfo.ConvertTimeToUtc(localDateTime, localTimeZone);
        }

        public static string ToHHmm(this DateTime time)
        {
            return time.ToString("HH:mm");
        }

        public static DateTime ToLocalDateTime(this DateTimeOffset dateTimeUtc)
        {
            return dateTimeUtc.ToLocalDateTime(null);
        }

        public static DateTime ToLocalDateTime(this DateTimeOffset dateTimeUtc, TimeZoneInfo localTimeZone)
        {
            localTimeZone = localTimeZone ?? TimeZoneInfo.Local;
            return TimeZoneInfo.ConvertTime(dateTimeUtc, localTimeZone).DateTime;
        }

        public static string ToRFC822Time(this DateTime date)
        {
            int hours = TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now).Hours;
            string str = "+" + hours.ToString().PadLeft(2, '0');
            if (hours < 0)
            {
                int num2 = hours * -1;
                str = "-" + num2.ToString().PadLeft(2, '0');
            }
            return date.ToString("ddd, dd MMM yyyy HH:mm:ss " + str.PadRight(5, '0'), CultureInfo.GetCultureInfo("en-US"));
        }

        public static DateTime ToSqlDate(this object obj)
        {
            DateTime time = Convert.ToDateTime(obj);
            DateTime time2 = SqlDateTime.MinValue.Value;
            if (time < time2)
            {
                return SqlDateTime.MinValue.Value;
            }
            DateTime time3 = SqlDateTime.MaxValue.Value;
            if (time > time3)
            {
                return SqlDateTime.MaxValue.Value;
            }
            return time;
        }

        public static string ToTime(this DateTime time)
        {
            return time.ToString("HH:mm:ss");
        }

        public static string ToUpper(this DateTime time)
        {
            int num;
            string str = "〇一二三四五六七八九";
            StringBuilder builder = new StringBuilder();
            string[] strArray = new string[] { time.Year.ToString(), time.Month.ToString("00"), time.Day.ToString("00") };
            for (int i = 0; i < strArray[0].Length; i++)
            {
                num = int.Parse(strArray[0].Substring(i, 1));
                builder.Append(str.Substring(num, 1));
            }
            builder.Append("年");
            for (int j = 0; j < strArray[1].Length; j++)
            {
                num = int.Parse(strArray[1].Substring(j, 1));
                if (j == 0)
                {
                    if (num > 0)
                    {
                        builder.Append("十");
                    }
                }
                else if (num > 0)
                {
                    builder.Append(str.Substring(num, 1));
                }
            }
            builder.Append("月");
            for (int k = 0; k < strArray[2].Length; k++)
            {
                num = int.Parse(strArray[2].Substring(k, 1));
                if (k == 0)
                {
                    if (num > 0)
                    {
                        if (num > 1)
                        {
                            builder.Append(str.Substring(num, 1));
                        }
                        builder.Append("十");
                    }
                }
                else if (num > 0)
                {
                    builder.Append(str.Substring(num, 1));
                }
            }
            builder.Append("日");
            return builder.ToString();
        }

        public static int WeekOfYear(this DateTime datetime)
        {
            DateTimeFormatInfo info = new DateTimeFormatInfo();
            CalendarWeekRule calendarWeekRule = info.CalendarWeekRule;
            DayOfWeek firstDayOfWeek = info.FirstDayOfWeek;
            return datetime.WeekOfYear(calendarWeekRule, firstDayOfWeek);
        }

        public static int WeekOfYear(this DateTime datetime, DayOfWeek firstDayOfWeek)
        {
            DateTimeFormatInfo info = new DateTimeFormatInfo();
            CalendarWeekRule calendarWeekRule = info.CalendarWeekRule;
            return datetime.WeekOfYear(calendarWeekRule, firstDayOfWeek);
        }

        public static int WeekOfYear(this DateTime datetime, CalendarWeekRule weekrule)
        {
            DateTimeFormatInfo info = new DateTimeFormatInfo();
            DayOfWeek firstDayOfWeek = info.FirstDayOfWeek;
            return datetime.WeekOfYear(weekrule, firstDayOfWeek);
        }

        public static int WeekOfYear(this DateTime datetime, CalendarWeekRule weekrule, DayOfWeek firstDayOfWeek)
        {
            return CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(datetime, weekrule, firstDayOfWeek);
        }
    }
}

